home *** CD-ROM | disk | FTP | other *** search
/ QRZ! Ham Radio 1 / QRZ Ham Radio Callsign Database - December 1993.iso / ucsd / packet / tcpip / amiga / asrc29k.lha / ax25subr.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-01-08  |  5.4 KB  |  251 lines

  1. #include <stdio.h>
  2. #include "global.h"
  3. #include "mbuf.h"
  4. #include "timer.h"
  5. #include "ax25.h"
  6. #include "lapb.h"
  7. #include <ctype.h>
  8.  
  9. struct ax25_cb *Ax25_cb[NHASH];
  10.  
  11. /* Default AX.25 parameters */
  12. int32 T3init = 0;        /* No keep-alive polling */
  13. int32 T4init = 300;        /* 5 Minutes of no I frame tx or rx => redundant link */
  14. int16 Maxframe = 1;        /* Stop and wait */
  15. int16 N2 = 10;            /* 10 retries */
  16. int16 Axwindow = 2048;        /* 2K incoming text before RNR'ing */
  17. int16 Paclen = 256;        /* 256-byte I fields */
  18. int16 Pthresh = 128;        /* Send polls for packets larger than this */
  19. int32 Axirtt = 5000;        /* Initial round trip estimate, ms */
  20. int16 Axversion = V2;        /* Protocol version */
  21. int32 Blimit = 30;        /* Retransmission backoff limit */
  22.  
  23. /* Address hash function. Exclusive-ORs each byte, ignoring
  24.  * such insignificant, annoying things as E and H bits
  25.  */
  26. int16
  27. ax25hash(s)
  28. char *s;
  29. {
  30.     register unsigned x;
  31.     register int i;
  32.  
  33.     x = 0;
  34.     for(i=ALEN; i!=0; i--)
  35.         x ^= *s++;
  36.     x &= 0xfe;
  37.     x ^= *s & SSID;
  38.     return (int16)(uchar(x) % NHASH);
  39. }
  40.  
  41. /* Look up entry in hash table */
  42. struct ax25_cb *
  43. find_ax25(addr)
  44. register char *addr;
  45. {
  46.     int16 hashval;
  47.     register struct ax25_cb *axp;
  48.  
  49.     /* Find appropriate hash chain */
  50.     hashval = ax25hash(addr);
  51.  
  52.     /* Search hash chain */
  53.     for(axp = Ax25_cb[hashval]; axp != NULLAX25; axp = axp->next){
  54.         if(addreq(axp->remote,addr)){
  55.             return axp;
  56.         }
  57.     }
  58.     return NULLAX25;
  59. }
  60.  
  61. /* Remove address entry from hash table */
  62. void
  63. del_ax25(axp)
  64. register struct ax25_cb *axp;
  65. {
  66.     int16 hashval;
  67.  
  68.     if(axp == NULLAX25)
  69.         return;
  70.     /* Remove from hash header list if first on chain */
  71.     hashval = ax25hash(axp->remote);
  72.  
  73.     /* Remove from chain list */
  74.     if(axp->prev == NULLAX25)
  75.         Ax25_cb[hashval] = axp->next;
  76.     else
  77.         axp->prev->next = axp->next;
  78.     if(axp->next != NULLAX25)
  79.         axp->next->prev = axp->prev;
  80.  
  81.     /* Timers should already be stopped, but just in case... */
  82.     stop_timer(&axp->t1);
  83.     stop_timer(&axp->t3);
  84.     stop_timer(&axp->t4);
  85.  
  86.     /* Free allocated resources */
  87.     free_q(&axp->txq);
  88.     free_q(&axp->rxasm);
  89.     free_q(&axp->rxq);
  90.     free((char *)axp);
  91. }
  92.  
  93. /* Create an ax25 control block. Allocate a new structure, if necessary,
  94.  * and fill it with all the defaults. The caller
  95.  * is still responsible for filling in the reply address
  96.  */
  97. struct ax25_cb *
  98. cr_ax25(addr)
  99. char *addr;
  100. {
  101.     register struct ax25_cb *axp;
  102.     int16 hashval;
  103.  
  104.     if(addr == NULLCHAR)
  105.         return NULLAX25;
  106.  
  107.     if((axp = find_ax25(addr)) == NULLAX25){
  108.         /* Not already in table; create an entry
  109.          * and insert it at the head of the chain
  110.          */
  111.         /* Find appropriate hash chain */
  112.         hashval = ax25hash(addr);
  113.         axp = (struct ax25_cb *)callocw(1,sizeof(struct ax25_cb));
  114.         /* Insert at beginning of chain */
  115.         axp->next = Ax25_cb[hashval];
  116.         if(axp->next != NULLAX25)
  117.             axp->next->prev = axp;
  118.         Ax25_cb[hashval] = axp;
  119.     }
  120.     axp->user = -1;
  121.     axp->state = LAPB_DISCONNECTED;
  122.     axp->maxframe = Maxframe;
  123.     axp->window = Axwindow;
  124.     axp->paclen = Paclen;
  125.     axp->proto = Axversion;    /* Default, can be changed by other end */
  126.     axp->pthresh = Pthresh;
  127.     axp->n2 = N2;
  128.     axp->srt = Axirtt / MSPTICK;
  129.     axp->t1.start = 2*axp->srt;
  130.     axp->t1.func = recover;
  131.     axp->t1.arg = axp;
  132.  
  133.     axp->t3.start = T3init / MSPTICK;
  134.     axp->t3.func = pollthem;
  135.     axp->t3.arg = axp;
  136.  
  137.     axp->t4.start = (T4init * 1000) / MSPTICK;
  138.     axp->t4.func = redundant;
  139.     axp->t4.arg = axp;
  140.  
  141.     /* Always to a receive and state upcall as default */
  142.     axp->r_upcall = s_arcall;
  143.     axp->s_upcall = s_ascall;
  144.  
  145.     return axp;
  146. }
  147.  
  148. /*
  149.  * setcall - convert callsign plus substation ID of the form
  150.  * "KA9Q-0" to AX.25 (shifted) address format
  151.  *   Address extension bit is left clear
  152.  *   Return -1 on error, 0 if OK
  153.  */
  154. int
  155. setcall(out,call)
  156. char *out;
  157. char *call;
  158. {
  159.     int csize;
  160.     unsigned ssid;
  161.     register int i;
  162.     register char *dp;
  163.     char c;
  164.  
  165.     if(out == NULLCHAR || call == NULLCHAR || *call == '\0'){
  166.         return -1;
  167.     }
  168.     /* Find dash, if any, separating callsign from ssid
  169.      * Then compute length of callsign field and make sure
  170.      * it isn't excessive
  171.      */
  172.     dp = strchr(call,'-');
  173.     if(dp == NULLCHAR)
  174.         csize = strlen(call);
  175.     else
  176.         csize = dp - call;
  177.     if(csize > ALEN)
  178.         return -1;
  179.     /* Now find and convert ssid, if any */
  180.     if(dp != NULLCHAR){
  181.         dp++;    /* skip dash */
  182.         ssid = atoi(dp);
  183.         if(ssid > 15)
  184.             return -1;
  185.     } else
  186.         ssid = 0;
  187.     /* Copy upper-case callsign, left shifted one bit */
  188.     for(i=0;i<csize;i++){
  189.         c = *call++;
  190.         if(islower(c))
  191.             c = toupper(c);
  192.         *out++ = c << 1;
  193.     }
  194.     /* Pad with shifted spaces if necessary */
  195.     for(;i<ALEN;i++)
  196.         *out++ = ' ' << 1;
  197.     
  198.     /* Insert substation ID field and set reserved bits */
  199.     *out = 0x60 | (ssid << 1);
  200.     return 0;
  201. }
  202.  
  203. int
  204. addreq(a,b)
  205. register char *a,*b;
  206. {
  207.     if(memcmp(a,b,ALEN) != 0 || ((a[ALEN] ^ b[ALEN]) & SSID) != 0)
  208.         return 0;
  209.     else
  210.         return 1;
  211. }
  212.  
  213. /* Convert encoded AX.25 address to printable string */
  214. char *
  215. pax25(e,addr)
  216. char *e;
  217. char *addr;
  218. {
  219.     register int i;
  220.     char c;
  221.     char *cp;
  222.  
  223.     cp = e;
  224.     for(i=ALEN;i != 0;i--){
  225.         c = (*addr++ >> 1) & 0x7f;
  226.         if(c != ' ')
  227.             *cp++ = c;
  228.     }
  229.     if ((*addr & SSID) != 0)
  230.         sprintf(cp,"-%d",(*addr >> 1) & 0xf);    /* ssid */
  231.     else
  232.         *cp = '\0';
  233.     return e;
  234. }
  235.  
  236. /* Figure out the frame type from the control field
  237.  * This is done by masking out any sequence numbers and the
  238.  * poll/final bit after determining the general class (I/S/U) of the frame
  239.  */
  240. int16
  241. ftype(control)
  242. register char control;
  243. {
  244.     if((control & 1) == 0)    /* An I-frame is an I-frame... */
  245.         return I;
  246.     if(control & 2)        /* U-frames use all except P/F bit for type */
  247.         return (int16)(uchar(control) & ~PF);
  248.     else            /* S-frames use low order 4 bits for type */
  249.         return (int16)(uchar(control) & 0xf);
  250. }
  251.